package com.zenithmind.common.interceptor;

import com.zenithmind.common.constant.CommonConstants;
import com.zenithmind.common.context.UserContext;
import com.zenithmind.common.security.JwtUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.web.servlet.HandlerInterceptor;

import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import java.util.Arrays;
import java.util.List;
import java.util.Map;

/**
 * 认证拦截器
 * 用于各个微服务验证来自网关的请求，并设置用户上下文
 */
@Slf4j
public class AuthInterceptor implements HandlerInterceptor {

    /**
     * 默认不需要认证的路径
     */
    private static final List<String> DEFAULT_SKIP_PATHS = Arrays.asList(
        "/actuator",
        "/swagger-ui",
        "/v3/api-docs",
        "/doc.html",
        "/webjars",
        "/favicon.ico",
        "/error"
    );

    /**
     * 自定义跳过认证的路径
     */
    private final List<String> skipPaths;

    /**
     * 是否启用严格模式（必须有用户信息）
     */
    private final boolean strictMode;

    public AuthInterceptor() {
        this(null, true);
    }

    public AuthInterceptor(List<String> skipPaths) {
        this(skipPaths, true);
    }

    public AuthInterceptor(List<String> skipPaths, boolean strictMode) {
        this.skipPaths = skipPaths;
        this.strictMode = strictMode;
    }

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        String path = request.getRequestURI();
        String method = request.getMethod();
        
        log.debug("AuthInterceptor处理请求: {} {}", method, path);

        // 检查是否需要跳过认证
        if (shouldSkipAuth(path)) {
            log.debug("路径 {} 跳过认证", path);
            return true;
        }

        try {
            // 从请求头中获取用户信息（由网关传递）
            String userId = request.getHeader(CommonConstants.USER_ID_HEADER);
            String userRoles = request.getHeader(CommonConstants.USER_ROLES_HEADER);

            if (StringUtils.isBlank(userId)) {
                // 如果没有用户ID，尝试从token中解析
                String token = extractToken(request);
                if (StringUtils.isNotBlank(token)) {
                    Map<String, Object> claims = JwtUtils.parseToken(token);
                    userId = JwtUtils.extractUserIdFromClaims(claims);
                    userRoles = JwtUtils.extractUserRolesFromClaims(claims);
                }
            }

            if (strictMode && StringUtils.isBlank(userId)) {
                log.warn("严格模式下用户ID为空，拒绝请求: {}", path);
                response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
                response.setContentType("application/json;charset=UTF-8");
                response.getWriter().write("{\"code\":401,\"message\":\"未授权：用户信息缺失\"}");
                return false;
            }

            // 设置用户上下文
            if (StringUtils.isNotBlank(userId)) {
                UserContext.setUserId(userId);
                if (StringUtils.isNotBlank(userRoles)) {
                    UserContext.setUserRoles(userRoles);
                }
                log.debug("设置用户上下文: userId={}, roles={}", userId, userRoles);
            }

            return true;
        } catch (Exception e) {
            log.error("认证拦截器处理失败: {}", e.getMessage(), e);
            if (strictMode) {
                response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
                response.setContentType("application/json;charset=UTF-8");
                response.getWriter().write("{\"code\":401,\"message\":\"认证失败\"}");
                return false;
            }
            return true;
        }
    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        // 清理用户上下文
        UserContext.clear();
    }

    /**
     * 判断是否应该跳过认证
     */
    private boolean shouldSkipAuth(String path) {
        // 检查默认跳过路径
        for (String skipPath : DEFAULT_SKIP_PATHS) {
            if (path.startsWith(skipPath)) {
                return true;
            }
        }

        // 检查自定义跳过路径
        if (skipPaths != null) {
            for (String skipPath : skipPaths) {
                if (skipPath.endsWith("/**")) {
                    String prefix = skipPath.substring(0, skipPath.length() - 3);
                    if (path.startsWith(prefix)) {
                        return true;
                    }
                } else if (path.equals(skipPath) || path.startsWith(skipPath)) {
                    return true;
                }
            }
        }

        return false;
    }

    /**
     * 从请求中提取token
     */
    private String extractToken(HttpServletRequest request) {
        // 首先尝试从token头获取
        String token = request.getHeader("token");
        
        // 如果没有，尝试从Authorization头获取
        if (StringUtils.isBlank(token)) {
            String authHeader = request.getHeader("Authorization");
            if (StringUtils.isNotBlank(authHeader)) {
                if (authHeader.startsWith("Bearer ")) {
                    token = authHeader.substring(7);
                } else if (authHeader.startsWith("ZenithMind ")) {
                    token = authHeader.substring(11);
                }
            }
        } else if (token.startsWith("ZenithMind ")) {
            token = token.substring(11);
        }
        
        return token;
    }
}
